#!/bin/bash

usage() {
	printf "\n%s\n\nTry ${0##*/} -h\n\n" "$@"
	exit 1
}

help() {
cat <<EOF

${0##*/} - Create pure HTML galleries with bash

If you call this script without arguments, it will look for images in the 
current folder, create thumbnails & HTML files in subfolders $thumbs and $data
and an index.html in the current folder.

Thus, the image files are in the gallery's base folder, still easily accessible
by other means, and everything else is neatly tucked away.

ANNOTATIONS

If there is a file called annotations in the same folder as the original images,
it will be parsed to add (short) annotations to the individual images' HTML
files.
The format is as follows:
imagefilename.ext: Some Annotation Text
Meaning:
At the immediate beginning of the line (no leading whitespace), the name of the
file, followed by a colon ':' (again, no space), followed by a single space.
Everything after that until the end of the line is the annotation.

CSS

The repository provides a gallery.css file, and I highly recommend you use it!
The resulting HTML does not use any javascript, and the CSS is an integral part
of the functionality.
The script will be looking for ~/.config/galbash/gallery.css and copy it to the
appropriate folder.

ALL OPTIONS

  -s dir     the source directory
             Default: $source

  -d dir     the destination directory (will be created)
             Default: $dest

  -b string  where the back button will take the visitor
             Default: $back

  -t int     Size of thumbnails in pixels. minimum: 10
             Default: $thumbsize

  -f string  the format extension for thumbnails
             Default: $thumbformat

  -F string  where the favicon is

  -T string  The title of the gallery.
             Default: $title

  -n         Do not wrap from last image to first and vice versa
             Default: false, i.e. wrapping is enabled

  -N         Do not create an index page with thumbnails
             Default: false, i.e. a thumbpage is created

  -k         Create symbolic links instead of copying the original files.
             This has no effect if source and destination are the same.
             Default: Copy

  -h         Display this help

See also: notabug.org/ohnonot/galbash
EOF
exit 1
}

source="."
dest="."
back="../" # where is the back button taking us
thumbsize=200
thumbformat=jpg
favicon=""
title="Image Gallery"
wrap=1 # wrap around from last image back to first and vice versa
link=0 # create symlinks instead of copying files
annotations=''
thumbs="thumbs"
data="data"
css="$HOME/.config/galbash/gallery.css"
thumbpage=1
toindex=""

while :; do
  case $1 in
    -s)	if [ -d "$2" ] && [ -r "$2" ]; then
			source="${2%/}" # remove possible trailing slash
			shift 2
		else
			usage "Option $1: $2 does not seem to be a readable directory"
		fi
      ;;
    -d)	if [[ "$2" == "-"* ]]; then
			usage "Option $1: $2 is invalid as destination (cannot start with \"-\")."
		else
			dest="${2%/}" # remove possible trailing slash
			shift 2
		fi
      ;;
    -b)	if [[ "$2" == "-"* ]]; then
			usage "Option $1: $2 is invalid (cannot start with \"-\")."
		else
			back="${2%/}" # remove possible trailing slash
			shift 2
		fi
      ;;
    -t)	if [[ "$2" =~ ^[1-9][0-9]+$ ]]; then
			thumbsize="$2"
			shift 2
		else
			usage "Option $1: $2 does not seem to be a positive integer, or is < 10."
		fi
      ;;
    -f)	if [[ "$2" =~ ^[a-zA-Z]+$ ]]; then
			thumbformat="$2"
			shift 2
		else
			usage "Option $1: $2 does not seem to be an image format."
		fi
      ;;
    -F)	if [[ "$2" == "-"* ]]; then
			usage "Option $1: $2 is invalid (cannot start with \"-\")."
		else
			favicon="<link rel=icon type='image/x-icon' href='$2'>"
			shift 2
		fi
      ;;
    -T)	if [[ "$2" == "-"* ]]; then
			usage "Option $1: $2 is invalid as a title (cannot start with \"-\")."
		else
			title="$2"
			shift 2
		fi
      ;;
    -n)	wrap=0
		shift
      ;;
    -N)	thumbpage=0
		shift
      ;;
    -k)	link=1
		shift
      ;;
    -h) help
      ;;
	*) break
	  ;;
  esac
done

echo "Source directory is $source
Destination is $dest"

# single quotes! eval'd later.
head='<!DOCTYPE html>
<html lang=en>
<head>
	<meta charset=utf-8>
	$favicon
	<title>$title</title>
	<link rel=stylesheet href="$css" type="text/css">
	<meta name=viewport content="width=device-width, initial-scale=1" />
</head>
<body class="$bodyclass">'

foot="</body>
</html>"

################################################################################

mkdir -p "$dest/"{"$thumbs","$data"} || usage "Could not create directories in\n\"$dest\""
[[ -r "$css" ]] && cp -f "$css" "$dest/data/gallery.css"

[ -r "$source/annotations" ] && annotations="$source/annotations"
amount=0
imagetext=()
for i in "$source"/*.* ; do
	type="$(file -b -L --mime-type "$i")"
	if [[ "$type" == "image/"* ]]; then # caveat: e.g. .xcf files are also images
		if [[ "$source" != "$dest" ]]; then
			if [[ "$link" == "1" ]]; then
				ln -s "$i" "$dest/"
			else
				cp "$i" "$dest/"
			fi
		fi
		# now we do some cleanup
		i="${i##*/}" # get filename without path
		if [[ "$annotations" != "" ]]; then
			imagetext[amount]="$(grep "^$i: " "$source/annotations")"
			imagetext[amount]="${imagetext[amount]#$i: }"
		fi
		new="${i//[^A-Za-z0-9._-]/_}"
		if [[ "$new" != "$i" ]]; then
			mv "$dest/$i" "$dest/$new" || usage "The file \"$dest/$i\"\ncould not be renamed to\n\"$dest/$new\"\nAborting."
		fi
		imgs[$((amount++))]="$new"
	fi
done

# create thumbs and fill arrays, make thumbnails
for ((i=0;i<amount;i++)); do
	thumb[i]="${imgs[i]%.*}.$thumbformat"
	convert "$dest/${imgs[i]}" -gravity center -crop 1:1 \
	-colorspace RGB +sigmoidal-contrast 11.6933 -define filter:filter=Sinc \
	-define filter:window=Jinc -define filter:lobes=3 -resize "$thumbsize" \
	-sigmoidal-contrast 11.6933 -colorspace sRGB "$dest/$thumbs/${thumb[i]}"
	# the above command apparently adds some enhancement
done

#############################################################################
# create thumbnail index page
if [[ "$thumbpage" == 1 ]]; then
	bodyclass="thumbpage"
	css="$data/gallery.css"
	output="$dest/index.html"
	
	eval "cat <<EOF
$head
EOF
" > "$output"
	
	cat <<EOF >> "$output"
	<div class="head clearfix">
		<span class=back><a href="$back" >«Back</a></span>
		<span class=title>$title</span>
	</div>
	<div class=content>
EOF

	for ((i=0;i<amount;i++)); do
		cat <<EOF
		<div class=thumb>
			<a href="$data/${imgs[i]%.*}.html" >
				<img title="Click to View" src="$thumbs/${thumb[i]}" />
			</a>
		</div>
EOF
	done >> "$output"
	
	echo -e "\t</div>\n$foot" >> "$output"
fi

#############################################################################
# create individual pages for each image, with previous/next buttons
bodyclass="fullpage"
title_pre="$title"
css="gallery.css"
[[ "$thumpage" == 1 ]] && back="../" && toindex=" to Index"

for ((i=0;i<amount;i++)); do
	output="$dest/$data/${imgs[i]%.*}.html"
	title="$title_pre - $((i + 1))/$amount"
	[[ "${imagetext[i]}" != "" ]] && text="${imagetext[i]}" || text="${imgs[i]}"

	eval "cat <<EOF
$head
EOF
" > "$output"

	cat <<EOF >> "$output"
	<div class="head clearfix">
		<span class=back><a href="$back" >«Back$toindex</a></span>
		<span class=imagetext><a title="View/Download" href="../${imgs[i]}">$text</a></span>
		<span class=title>$title</span>
	</div>
	<div class=content>
		<div class="thumb previous">
EOF

	# calculate previous thumb
	showthumb=0
	if (( i == 0 )); then
		if [[ "$wrap" == "1" ]]; then
			j=$(( amount - 1 ))
			showthumb=1
		fi
	else
		j="$((i - 1))"
		showthumb=1
	fi
	[[ "$showthumb" == 1 ]] && cat <<EOF >> "$output"
			<a href="${imgs[j]%.*}.html">
				<img title=Previous src="../$thumbs/${thumb[j]}" />
			</a>
EOF

	# full image
	cat <<EOF >> "$output"
		</div>
		<div class=full>
			<img src="../${imgs[i]}"/>
		</div>
		<div class="thumb next">
EOF

	# calculate next thumb
	showthumb=0
	if (( i == ( amount - 1 ) )); then
		if [[ "$wrap" == "1" ]]; then
			j=0
		showthumb=1
		fi
	else
		j="$((i + 1))"
		showthumb=1
	fi
	[[ "$showthumb" == 1 ]] && cat <<EOF >> "$output"
			<a href="${imgs[j]%.*}.html" >
				<img title=Next src="../$thumbs/${thumb[j]}" />
			</a>
EOF

	echo -e "\t\t</div>\n\t</div>\n$foot" >> "$output"

done
